package com.danskin.wechat.util;

import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;

/**
 *
 * @author xxj
 */
public class FTPHelper implements Closeable {

	private static final String IMAGE_DOMAIN = PropertyUtil.get("image_domain");
	private static final String FTP_REMOTE_IP = PropertyUtil.get("ftp_remote_ip");
	private static final String FTP_REMOTE_PORT = PropertyUtil.get("ftp_remote_port");
	private static final String FTP_USERNAME = PropertyUtil.get("ftp_username");
	private static final String FTP_PASSWORD = PropertyUtil.get("ftp_password");
	private static final String FTP_ROOT_PATH = PropertyUtil.get("ftp_root_path");
	private static final String FTP_IS_PASV = PropertyUtil.get("ftp_is_pasv");// 是否是被动

	private FTPClient ftp = null;
	boolean _isLogin = false;
	private String ftpRootPath = "";

	public static FTPHelper getInstance() {
		return new FTPHelper();
	}

	private FTPHelper() {
		this.ftpRootPath = FTP_ROOT_PATH;
		int port = Integer.valueOf(FTP_REMOTE_PORT);

		this.login(FTP_REMOTE_IP, port, FTP_USERNAME, FTP_PASSWORD);
	}

	/**
	 * 
	 * ftp 匿名登录
	 * 
	 * @param ip
	 *            ftp服务地址
	 * @param port
	 *            端口号
	 * @param uname
	 *            用户名
	 * @param pass
	 *            密码
	 */
	// public boolean login(String ip, int port) {
	// // 如果没有设置ftp用户可将username设为anonymous，密码为任意字符串
	// return login(ip, port, "anonymous", "");
	// }

	/**
	 * 
	 * ftp登录
	 * 
	 * @param ip
	 *            ftp服务地址
	 * @param port
	 *            端口号
	 * @param uname
	 *            用户名
	 * @param pass
	 *            密码
	 * @param workingDir
	 *            ftp 根目目录
	 */
	public boolean login(String ip, int port, String uname, String pass) {
		ftp = new FTPClient();
		try {
			// 连接
			ftp.connect(ip, port);
			_isLogin = ftp.login(uname, pass);

			// 检测连接是否成功
			int reply = ftp.getReplyCode();
			if (!FTPReply.isPositiveCompletion(reply)) {

				return false;
			}
			return true;
		} catch (Exception ex) {
			ex.printStackTrace();
			return false;
		}
	}

	/**
	 * 上传后触发
	 */
	// public Function<FtpFileInfo, Boolean> onUploadFileAfter;
	/**
	 * 上传文件
	 * 
	 * @param localFileName
	 * @param ftpDirName
	 * @param ftpFileName
	 * @return
	 */
	public boolean uploadFile(String localFileName, String ftpDirName, String ftpFileName) {

		return uploadFile(localFileName, this.ftpRootPath, ftpDirName, ftpFileName, true);
	}
	/**
	 * 
	 * ftp上传文件
	 * 
	 * @param localFileName
	 *            待上传文件
	 * @param ftpDirName
	 *            ftp 目录名
	 * @param ftpFileName
	 *            ftp目标文件
	 * @return true||false
	 */
	// public boolean uploadFile(String localFileName, String ftpRootPath,
	// String ftpDirName, String ftpFileName) {
	// this.ftpRootPath = ftpRootPath;
	// return uploadFile(localFileName, ftpRootPath, ftpDirName, ftpFileName,
	// false);
	// }

	/**
	 * 
	 * ftp上传文件
	 * 
	 * @param localFileName
	 *            待上传文件
	 * @param ftpDirName
	 *            ftp 目录名
	 * @param ftpFileName
	 *            ftp目标文件
	 * @param deleteLocalFile
	 *            是否删除本地文件
	 * @return true||false
	 */
	public boolean uploadFile(String localFileName, String ftpRootPath, String ftpDirName, String ftpFileName,
			boolean deleteLocalFile) {
		this.ftpRootPath = ftpRootPath;
		// if(StringExtend.isNullOrEmpty(ftpDirName))
		// ftpDirName="/";
		if (StringUtil.isNullOrEmpty(ftpFileName))
			throw new RuntimeException("上传文件必须填写文件名！");

		File srcFile = new File(localFileName);
		if (!srcFile.exists())
			throw new RuntimeException("文件不存在：" + localFileName);
		try {
			FileInputStream fis = new FileInputStream(srcFile);
			// 上传文件
			boolean flag = uploadFile(fis, ftpDirName, ftpFileName);
			// 上传前事件
			// if(onUploadFileAfter!=null){
			// onUploadFileAfter.apply(new
			// FtpFileInfo(localFileName,ftpDirName,ftpFileName));
			// }
			// 删除文件
			if (deleteLocalFile) {
				srcFile.delete();

			}
			fis.close();
			return flag;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		} finally {
		}
	}

	/**
	 * 
	 * ftp上传文件 (使用inputstream)
	 * 
	 * @param localFileName
	 *            待上传文件
	 * @param ftpDirName
	 *            ftp 目录名
	 * @param ftpFileName
	 *            ftp目标文件
	 * @return true||false
	 */
	private boolean uploadFile(FileInputStream uploadInputStream, String ftpDirName, String ftpFileName) {
		// if(StringExtend.isNullOrEmpty(ftpDirName))
		// ftpDirName="/";
		if (StringUtil.isNullOrEmpty(ftpFileName))
			throw new RuntimeException("上传文件必须填写文件名！");

		try {
			// 设置上传目录(没有则创建)
			ftpDirName = this.ftpRootPath + "/" + StringUtil.trimStart(ftpDirName, "/");
			if (!createDir(ftpDirName)) {
				throw new RuntimeException("切入FTP目录失败：" + ftpDirName);
			}
			ftp.setBufferSize(1024);
			// 解决上传中文 txt 文件乱码
			ftp.setControlEncoding("GBK");
			// 设置被动模式
			if (FTP_IS_PASV.equals("1")) {
				ftp.enterLocalPassiveMode();
			}
			// 设置文件类型（二进制）
			ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
			// 上传
			String fileName = new String(ftpFileName.getBytes("UTF-8"), "iso-8859-1");
			if (ftp.storeFile(fileName, uploadInputStream)) {
				uploadInputStream.close();

				return true;
			}

			return false;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		} finally {

		}
	}

	/**
	 * 下载文件
	 * 
	 * @param ftpDirName
	 *            ftp目录名
	 * @param ftpFileName
	 *            ftp文件名
	 * @param localFileFullName
	 *            本地文件名
	 * @return
	 * @author xxj
	 */
	public boolean downloadFile(String ftpDirName, String ftpFileName, String localFileFullName) {
		try {
			if ("".equals(ftpDirName))
				ftpDirName = "/";
			String dir = new String(ftpDirName.getBytes("GBK"), "iso-8859-1");
			if (!ftp.changeWorkingDirectory(dir)) {
				System.out.println("切换目录失败：" + ftpDirName);
				return false;
			}
			FTPFile[] fs = ftp.listFiles();
			String fileName = new String(ftpFileName.getBytes("GBK"), "iso-8859-1");
			for (FTPFile ff : fs) {
				if (ff.getName().equals(fileName)) {
					FileOutputStream is = new FileOutputStream(new File(localFileFullName));
					ftp.retrieveFile(ff.getName(), is);
					is.close();
					System.out.println("下载ftp文件已下载：" + localFileFullName);
					return true;
				}
			}
			System.out.println("下载ftp文件失败：" + ftpFileName + ";目录：" + ftpDirName);
			return false;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 
	 * 删除ftp上的文件
	 * 
	 * @param ftpFileName
	 * @return true || false
	 */
	public boolean removeFile(String ftpFileName) {
		boolean flag = false;

		try {
			ftpFileName = new String(ftpFileName.getBytes("GBK"), "iso-8859-1");
			flag = ftp.deleteFile(ftpFileName);

			return flag;
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 删除空目录
	 * 
	 * @param dir
	 * @return
	 */
	public boolean removeDir(String dir) {
		if (StringUtils.startsWith(dir, "/"))
			dir = "/" + dir;
		try {
			String d = new String(dir.toString().getBytes("GBK"), "iso-8859-1");
			return ftp.removeDirectory(d);
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 创建目录(有则切换目录，没有则创建目录)
	 * 
	 * @param dir
	 * @return
	 */
	public boolean createDir(String dir) {
		if (StringUtil.isNullOrEmpty(dir))
			return true;
		String d;
		try {
			// 目录编码，解决中文路径问题
			d = new String(dir.toString().getBytes("GBK"), "iso-8859-1");
			// 尝试切入目录
			if (ftp.changeWorkingDirectory(d))
				return true;

			dir = StringUtil.trimStart(dir, "/");
			dir = StringUtil.trimEnd(dir, "/");
			String[] arr = dir.split("/");
			StringBuffer sbfDir = new StringBuffer();
			// 循环生成子目录
			for (String s : arr) {
				sbfDir.append("/");
				sbfDir.append(s);
				// 目录编码，解决中文路径问题
				d = new String(sbfDir.toString().getBytes("GBK"), "iso-8859-1");
				// 尝试切入目录
				if (ftp.changeWorkingDirectory(d))
					continue;
				if (!ftp.makeDirectory(d)) {
					// System.out.println("[失败]ftp创建目录：" + sbfDir.toString());
					return false;
				}
				// System.out.println("[成功]创建ftp目录：" + sbfDir.toString());
			}
			// 将目录切换至指定路径
			return ftp.changeWorkingDirectory(d);
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 *
	 * 销毁ftp连接
	 *
	 */
	private void closeFtpConnection() {
		_isLogin = false;
		if (ftp != null) {
			if (ftp.isConnected()) {
				try {
					ftp.logout();
					ftp.disconnect();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 *
	 * 销毁ftp连接
	 *
	 */
	@Override
	public void close() {
		this.closeFtpConnection();
	}

	public static class FtpFileInfo {
		public FtpFileInfo(String srcFile, String ftpDirName, String ftpFileName) {
			this.ftpDirName = ftpDirName;
			this.ftpFileName = ftpFileName;
			this.srcFile = srcFile;
		}

		String srcFile;
		String ftpDirName;
		String ftpFileName;
		String ftpFileFullName;

		public String getSrcFile() {
			return srcFile;
		}

		public void setSrcFile(String srcFile) {
			this.srcFile = srcFile;
		}

		public String getFtpDirName() {
			return ftpDirName;
		}

		public void setFtpDirName(String ftpDirName) {
			this.ftpDirName = ftpDirName;
		}

		public String getFtpFileName() {
			return ftpFileName;
		}

		public void setFtpFileName(String ftpFileName) {
			this.ftpFileName = ftpFileName;
		}

		/**
		 * 获取ftp上传文件的完整路径名
		 * 
		 * @return
		 * @author xxj
		 */
		public String getFtpFileFullName() {
			return StringUtil.combine("/", ftpDirName, ftpFileName);
		}

		public static void main(String[] args) {
			boolean b = FTPHelper.getInstance().uploadFile("D:/1.jpg", "dd", StringUtil.getShortUUID() + ".jpg");

			System.out.println(b);
		}

	}

	/**
	 * 上传图片到本地
	 * 
	 * @param file
	 * @throws IllegalStateException
	 * @throws IOException
	 */
	public static void uploadPicture(MultipartFile file, String localFolder) throws IllegalStateException, IOException {
		String fileName = file.getOriginalFilename();
		String pic_path = localFolder;
		File targetFile = new File(pic_path, fileName);
		if (!targetFile.exists()) {
			targetFile.mkdirs();
		}
		file.transferTo(targetFile);
	}

	public String uploadPictureAndReturnPictureUrl(MultipartFile file, String businessFolder, String localFolder)
			throws IllegalStateException, IOException {
		// 上传图片到本地
		uploadPicture(file, localFolder);

		// 生成图片路径
		String path = localFolder + "/" + file.getOriginalFilename();
		String fileNameSerialize = FTPHelper.getShortUUID() + ".jpg";
		// aaaaaaaaaaaaaaaa

		// 上传文件到ftp服务器
		FTPHelper.getInstance().uploadFile(path, businessFolder, fileNameSerialize);

		String pathUrl = IMAGE_DOMAIN + "/" + businessFolder + "/" + fileNameSerialize;
		return pathUrl;
	}

	public String uploadPictureAndReturnPictureUrlDetails(File file, String businessFolder, String localFolder)
			throws IllegalStateException, IOException {
		FileInputStream input = new FileInputStream(file);
		MultipartFile multipartFile = new MockMultipartFile("file", file.getName(), "text/plain",
				IOUtils.toByteArray(input));
		// 上传图片到本地
		uploadPicture(multipartFile, localFolder);
		// 生成图片路径
		String path = localFolder + "/" + file.getName();
		String fileNameSerialize = FTPHelper.getShortUUID() + ".jpg";

		// 上传文件到ftp服务器
		FTPHelper.getInstance().uploadFile(path, businessFolder, fileNameSerialize);

		String pathUrl = IMAGE_DOMAIN + "/" + businessFolder + "/" + fileNameSerialize;
		return pathUrl;
	}

	public Map uploadPictureAndReturnPictureUrlList(MultipartFile[] file, String businessFolder, String localFolder,
			int leng) throws IllegalStateException, IOException {
		Map<Object, String> mapImg = new HashMap<Object, String>();
		for (int i = 0; i < file.length; i++) {
			if (i < leng) {
				continue;
			}
			MultipartFile files = file[i];
			if (files.isEmpty()) {
				continue;
			}
			// 上传图片到本地
			uploadPicture(files, localFolder);
			// 生成图片路径
			String path = localFolder + "/" + files.getOriginalFilename();
			String fileNameSerialize = FTPHelper.getShortUUID() + ".jpg";
			// 上传文件到ftp服务器
			FTPHelper.getInstance().uploadFile(path, businessFolder, fileNameSerialize);

			String pathUrl = IMAGE_DOMAIN + "/" + businessFolder + "/" + fileNameSerialize;
			mapImg.put(i, pathUrl);
		}
		return mapImg;
	}

	/**
	 * 上传本地二维码到ftp服务器
	 * 
	 * @param localQrCode
	 * @param businessFolder
	 * @return
	 * @author makunsmac
	 */
	public String uploadQrCode(String localQrCode, String businessFolder) {
		String qrcodeName = FTPHelper.getShortUUID() + ".jpg";

		// 上传文件到ftp服务器
		FTPHelper.getInstance().uploadFile(localQrCode, businessFolder, qrcodeName);

		String pathUrl = IMAGE_DOMAIN + "/" + businessFolder + "/" + qrcodeName;
		return pathUrl;
	}

	public static String getShortUUID() {
		return UUID.randomUUID().toString().replaceAll("-", "");
	}

	/**
	 * 保存临时图片
	 * 
	 * @return
	 */
	public static String uploadTemporaryFile() {
		String filetemp = System.getProperty("catalina.home") + File.separator + "danskin-temp";
		return filetemp;
	}

	public static String uploadTemporaryFile(String i) {
		String filetemp = System.getProperty("catalina.home") + File.separator + "danskin-temp" + File.separator + i;
		return filetemp;
	}
}